#include "LoadShader.h"
#include <fstream>
#include <iostream>
using namespace std;

GLuint LoadShade(const ShaderInfo *si)
{
    GLuint program = glCreateProgram();

    ifstream file;
    streamoff len = 0;
    int i = 0;
    char *buf = nullptr;
    GLuint shader = 0;
    while (GL_NONE != si[i].type)
    {
        file.open(si[i].source, ifstream::binary);
        file.seekg(0, file.end);
        len = file.tellg();
        file.seekg(0, file.beg);
        if (len == 0 || !file.good())
        {
            cerr << si[i].type << " Shader source is Empty Or File is not exist. (" << si[i].source << ")" << endl;
            glDeleteProgram(program);
            return 0;
        }

        buf = new char[(unsigned int)len+1];
        buf[len] = '\0';
        file.read(buf, len);
        file.clear();
        file.close();
        shader = LoadShade(si[i].type, buf);
        delete[] buf;
        if (shader == 0)
        {
            cerr <<" (" << si[i].source << ")" << endl;
            glDeleteProgram(program);
            return 0;
        }
        glAttachShader(program, shader);
        glDeleteShader(shader);
        i++;
    }

    glLinkProgram(program);

    GLint linked = 1;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    
    if (!linked)
    {
        GLsizei len;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
        char *log = new char[len+1];
        glGetProgramInfoLog(program, len, &len, log);
        cerr << "Shader Linking error: " << log << endl;
        delete[] log;
        glDeleteProgram(program);
        return 0;
    }

    return program;
}

GLuint LoadShade(GLenum type, const char*source)
{
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    GLint compiled = 1;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (!compiled)
    {
        GLsizei len = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
        char *log = new char[len+1];
        glGetShaderInfoLog(shader, len, &len, log);
        cerr << type << "  " << "Shader compilation failed: " << log;
        delete[] log;
        glDeleteShader(shader);
        return 0;
    }

    return shader;
}

